/**
 * @name: 格式化金钱
 * @description: 将字符串或数字修改格式为xxx,xxx,xxx
 * @param {number | string} num
 * @return: xxx,xxx,xxx
 */
export const ThousandNum = (num: number | string) => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
/**
 * @name: 格式化金钱
 * @description: 将xxx,xxx,xxx修改格式数字
 * @param {string} val
 * @return: Number
 */
export const changeNumber = (val: string) => {
  if (val) {
    const a = `${val}`.replace(/,/g, '');
    return Number(a);
  }
  return 0;
};
/**
 * @name: 判断数据类型
 * @description: 判断数据类型是什么或者是否与传入类型一致
 * @param {any} tgt 要判断的参数
 * @param {string} type 要对比的类型
 * @return: boolean | string
 */
export const DataType = (tgt: any, type: string) => {
  const dataType = Object.prototype.toString
    .call(tgt)
    .replace(/\[object (\w+)\]/, '$1')
    .toLowerCase();
  return type ? dataType === type : dataType;
};
/**
 * @name: 是否为空数组
 * @description: 判断参数是否为数组并且为空
 * @param {any} arr 要判断的参数
 * @return: boolean
 */
export const isEmptyArr = (arr: any) => Array.isArray(arr) && !arr.length;
/**
 * @name: 是否为空对象
 * @description: 判断参数是否为对象并且为空对象
 * @param {any} obj 要判断的参数
 * @return: boolean
 */
export const isEmptyObj = (obj: any) => DataType(obj, 'object') && !Object.keys(obj).length;
/**
 * @name: 去重数组
 * @param {Array} arr 要去重的数组
 * @return: Array
 */
export const arrSet = (arr: any[]) => [...new Set([...arr])];
/**
 * @name: 过滤空值
 * @description: 过滤数组空值
 * @param {Array} arr 过滤数组空值
 * @return: Array
 */
export const arrFilterEmptyValue = (arr: any[]) => [...arr].filter(Boolean);

/**
 * @name: 构造树型结构数据
 * @param {Array<any>} data 数据源
 * @param {string} id id字段 默认 'id'
 * @param {string} name name字段 默认 'name'
 * @param {string} parentId 父节点字段 默认 'parentId'
 * @param {string} parentName
 * @param {string} children 子节点数据字段 默认 'children'
 */
export function buildTreeData(
  data: any[],
  id: string,
  name: string,
  parentId: string,
  parentName: string,
  children: string,
) {
  const config = {
    id: id || 'id',
    name: name || 'name',
    parentId: parentId || 'parentId',
    parentName: parentName || 'parentName',
    childrenList: children || 'children',
  };

  const childrenListMap = {};
  const nodeIds = {};
  const tree: any[] = [];
  data.forEach(
    (item: {
      id: string;
      name: string;
      key: string;
      title: string;
      value: any;
    }) => {
      const d = item;
      const pId = d[config.parentId];
      if (childrenListMap[pId] === null) {
        childrenListMap[pId] = [];
      }
      d.key = d[config.id];
      d.title = d[config.name];
      d.value = d[config.id];
      nodeIds[d[config.id]] = d;
      childrenListMap[pId].push(d);
    },
  );

  data.forEach((item: any) => {
    const d = item;
    const pId = d[config.parentId];
    if (nodeIds[pId] === null) {
      d[config.parentName] = '';
      tree.push(d);
    }
  });

  function adaptToChildrenList(item: any) {
    const o = item;
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]];
    }
    if (o[config.childrenList]) {
      o[config.childrenList].forEach((child: any) => {
        const c = child;
        c[config.parentName] = o[config.name];
        adaptToChildrenList(c);
      });
    }
  }

  tree.forEach((t: any) => {
    adaptToChildrenList(t);
  });

  return tree;
}
/**
 * @name: 引用数据类型深拷贝
 * @param {Object} source 原对象
 * @return: Object
 */
export const deepClone = (source: any) => {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments');
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach((keys: string | number) => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
};
/**
 * @name: 删除对应键值对
 * @param {Object} params 原对象
 * @param {string[]} arrs 要删除的键
 * @return: Object
 */
export const deleteKeys = (params: any, arrs: string[]) => {
  const param = deepClone(params);
  for (let i = 0; i <= arrs.length; i++) {
    Reflect.deleteProperty(param, arrs[i]);
  }
  return param;
};

/**
 * @name: 限制只能输入数字及小数点后两位
 * @description: 限制只能输入数字及小数点后两位
 * @param {string} str 输入值
 * @param {number} num 小数点前位数限制
 * @return string
 */
export const onlyNumberAndTwoDecimal = (str: string, num?: number) => {
  // eslint-disable-next-line no-param-reassign
  str = str.replace(/[^\d.]/g, '');
  // eslint-disable-next-line no-param-reassign
  str = str.replace(/^\./g, '');
  // eslint-disable-next-line no-param-reassign
  str = str.replace(/\.{2,}/g, '');
  // eslint-disable-next-line no-param-reassign
  str = str.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
  if (num) {
    // eslint-disable-next-line no-param-reassign
    str = str.indexOf('.') > 0
      ? `${str.split('.')[0].substring(0, num)}.${str
        .split('.')[1]
        .substring(0, 2)}`
      : str;
  } else {
    // eslint-disable-next-line no-param-reassign
    str = str.indexOf('.') > 0
      ? `${str.split('.')[0]}.${str.split('.')[1].substring(0, 2)}`
      : str;
  }

  if (str.length > 1 && str[0] === '0' && str[1] !== '.') {
    // eslint-disable-next-line no-param-reassign
    str = str.slice(0);
  }
  return str;
};
/**
 * @name: 格式化时间
 * @param {string} fmt 格式化模板
 * @param {Date} date 日期
 * @return string
 */
export const dateFormatMethod = (fmt: string, date: Date) => {
  let ret;
  const opt = {
    'Y+': date.getFullYear().toString(), // 年
    'M+': (date.getMonth() + 1).toString(), // 月
    'd+': date.getDate().toString(), // 日
    'D+': date.getDate().toString(), // 日
    'H+': date.getHours().toString(), // 时
    'm+': date.getMinutes().toString(), // 分
    's+': date.getSeconds().toString(), // 秒
    // 有其他格式化字符需求可以继续添加，必须转化成字符串
  };
  // eslint-disable-next-line guard-for-in,no-restricted-syntax
  for (const k in opt) {
    ret = new RegExp(`(${k})`).exec(fmt);
    if (ret) {
      // eslint-disable-next-line no-param-reassign
      fmt = fmt.replace(
        ret[1],
        ret[1].length === 1
          ? opt[k as keyof typeof opt]
          : opt[k as keyof typeof opt].padStart(ret[1].length, '0'),
      );
    }
  }
  return fmt;
};
/**
 * @name: 去除空格
 * @description: type: 1-所有空格 2-前后空格 3-前空格 4-后空格
 * @param {string} str
 * @param {1 | 2 | 3 | 4} type
 * @return string
 */
export const trim = (str: string, type: 1 | 2 | 3 | 4) => {
  // eslint-disable-next-line no-param-reassign
  type = type || 1;
  switch (type) {
    case 1:
      return str.replace(/\s+/g, '');
    case 2:
      return str.replace(/(^\s*)|(\s*$)/g, '');
    case 3:
      return str.replace(/(^\s*)/g, '');
    case 4:
      return str.replace(/(\s*$)/g, '');
    default:
      return str;
  }
};
/**
 * @name: 字符转换
 * @description: type: 1:首字母大写 2：首字母小写 3：大小写转换 4：全部大写 5：全部小写
 * @param {string} str
 * @param {1 | 2 | 3 | 4 | 5} type
 * @return string
 */
export const changeCase = (str: string, type: 1 | 2 | 3 | 4 | 5) => {
  // eslint-disable-next-line no-param-reassign
  type = type || 4;
  switch (type) {
    case 1:
      return str.replace(
        /\b\w+\b/g,
        (word) => word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(),
      );
    case 2:
      return str.replace(
        /\b\w+\b/g,
        (word) => word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase(),
      );
    case 3:
      return str
        .split('')
        .map((word) => {
          if (/[a-z]/.test(word)) {
            return word.toUpperCase();
          }
          return word.toLowerCase();
        })
        .join('');
    case 4:
      return str.toUpperCase();
    case 5:
      return str.toLowerCase();
    default:
      return str;
  }
};

/**
 * 参数处理
 * @param {*} params  参数
 * @return {string}
 */
export function tansParams(params) {
  let result = '';
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    const part = `${encodeURIComponent(propName)}=`;
    if (value !== null && value !== '' && typeof (value) !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== '' && typeof (value[key]) !== 'undefined') {
            const newParams = `${propName}[${key}]`;
            const subPart = `${encodeURIComponent(newParams)}=`;
            result += `${subPart + encodeURIComponent(value[key])}&`;
          }
        }
      } else {
        result += `${part + encodeURIComponent(value)}&`;
      }
    }
  }
  return result;
}
